#pragma once
#include <msgpack.hpp>
#include <unordered_map>
#include "log.h"
/**
 * 一些固定的打包封装函数放在这里
 * 传输的包数据是二进制
 * 底层接收和发送函数的参数：(string data, size_t, size)
 * @param data 二进制数据
 * @param size 二进制数据长度
 */

 // 前置函数声明
std::string Pack2CPP(std::unordered_map<std::string, std::string>& data);// 打包函数
bool UnPackFromCPP(const std::string& str, std::unordered_map<std::string, std::string>& data);// 拆包函数
std::string Pack2Lua(const std::unordered_map<std::string, std::string>& data);// 打包函数
bool UnPackFromLua(const std::string& str, std::unordered_map<std::string, std::string>& data);// 拆包函数

/**
 * 打包函数
 * @param data 参数只接受map, 键值对都会打包
 * @return 返回序列化后的二进制字符串
 */
std::string Pack2CPP(std::unordered_map<std::string, std::string>& data){
    // 1.创建一个MessagePack缓冲区
    msgpack::sbuffer sbuf;
    
    // 2.使用pack()函数打包map数据
    msgpack::pack(sbuf, data);

    // 3.返回打包后的二进制数据
    return std::string(sbuf.data(), sbuf.size());
}

/**
 * 拆包函数
 * @param str 传入的二进制字符串
 * @param data 传出参数，获得原始映射
 */
bool UnPackFromCPP(const std::string& str, std::unordered_map<std::string, std::string>& data){
    if(str.empty()) {
        Log_Error(0, "传入进行拆包的字符串不能为空");
        return false;
    }
    
    try {
        // 1.创建解包对象
        msgpack::object_handle oh = msgpack::unpack(str.data(), str.size());
        msgpack::object obj = oh.get();
        
        // 2.将解包数据转换为unordered_map
        obj.convert(data);
        return true;
    } catch (const std::exception& e) {
        // 处理解包过程中的异常(改用日志避免影响程序运行)
        Log_Error(0, "拆包出现异常: %s", std::string(e.what()));
        //throw std::runtime_error("Unpack failed: " + std::string(e.what()));
        return false;
    }
}

/**
 * 打包函数
 * @param data 参数只接受map, 键值对都会打包
 * @return 返回序列化后的二进制字符串
 */
std::string Pack2Lua(const std::unordered_map<std::string, std::string>& data){
    // 1. 创建MessagePack缓冲区
    msgpack::sbuffer sbuf;

    // 2.转换为兼容关联数组格式
    msgpack::type::assoc_vector<std::string, std::string> av;
    av.reserve(data.size());
    for(const auto& pair : data){
        av.emplace_back(pair.first,pair.second);
    }

    // 3.打包数据
    msgpack::pack(sbuf, av);

    // 4.返回二进制数据
    return std::string(sbuf.data(), sbuf.size());
}

/**
 * 拆包函数
 * @param str 传入的二进制字符串
 * @param data 传出参数，获得原始映射
 */
bool UnPackFromLua(const std::string& str, std::unordered_map<std::string, std::string>& data){
    if(str.empty()) {
        Log_Error(0, "传入进行拆包的字符串不能为空");
        return false;
    }

    try{
        // 1.反序列化数据
        msgpack::object_handle oh = msgpack::unpack(str.data(), str.size());
        msgpack::object obj = oh.get();

        if (obj.type != msgpack::type::MAP) {
            Log_Error(0, "Expected MAP type, got %d", obj.type);
            return false;
        }

        // 直接遍历 msgpack::object_map
        msgpack::object_map map = obj.via.map;
        for (uint32_t i = 0; i < map.size; ++i) {
            std::string key, value;
            map.ptr[i].key.convert(key);    // 解析 key
            map.ptr[i].val.convert(value);  // 解析 value
            data.emplace(key, value);
        }
        return true;
    }catch(const std::exception& e){
        // 处理解包过程中的异常(改用日志避免影响程序运行)
        Log_Error(0, "拆包出现异常: %s", std::string(e.what()));
        return false;
    }
}